import logging

import pytz
from aiogram import Bot
from arq import cron

from dc_shop.config import load_config
from dc_shop.core.constants import LOCALES_FOLDER
from dc_shop.core.logger import configure_logging
from dc_shop.database.main import build_sa_engine, build_sa_session_factory
from dc_shop.database.services import BotSettingsService
from dc_shop.database.services.discount import DiscountService
from dc_shop.database.services.order import OrderService
from dc_shop.database.services.payment_method import PaymentMethodService
from dc_shop.database.services.product import ProductService
from dc_shop.database.services.promocode import PromocodeService
from dc_shop.database.services.shop import ShopService
from dc_shop.database.services.user import UserService
from dc_shop.database.uow.uow import build_uow
from dc_shop.tg_bot.services.locale import configure_localizator
from dc_shop.worker.jobs import (
    auto_enable_bot,
    notify_expired_payment,
    notify_expiring_payment,
    notify_user,
    notify_users,
    send_cart_confirmation_msg,
)
from dc_shop.worker.jobs.auto_close_orders import auto_close_completed_orders, free_stock_in_cancelled_orders

config = load_config()

logger = logging.getLogger(__name__)


def generate_run_time(x: int, start: int, end: int) -> set:
    """Generate set with x period between start and end interval"""

    return {*list(range(start, end, x))}


async def startup(ctx):
    configure_logging()
    logger.info("Starting worker")
    engine = build_sa_engine(config.db)
    ctx["engine"] = engine
    ctx["sessionmaker"] = build_sa_session_factory(engine)
    ctx["config"] = config
    ctx["bot"] = Bot(token=config.tg_bot.token, parse_mode="HTML")
    ctx["localizator"] = configure_localizator(LOCALES_FOLDER)


async def on_job_start(ctx):
    """Прокидываем зависимости в задачу"""

    session = ctx["sessionmaker"]()
    uow = build_uow(session)
    ctx["session"] = session
    ctx["uow"] = uow
    ctx["user_service"] = UserService(uow)
    ctx["order_service"] = OrderService(uow)
    ctx["product_service"] = ProductService(uow)
    ctx["shop_service"] = ShopService(uow)
    ctx["payment_method_service"] = PaymentMethodService(uow)
    ctx["discount_service"] = DiscountService(uow)
    ctx["promocode_service"] = PromocodeService(uow)
    ctx["bot_settings_service"] = BotSettingsService(uow)


async def after_job_end(ctx):
    if ctx.get("session"):
        await ctx["session"].close()


async def shutdown(ctx):
    if ctx.get("session"):
        await ctx["session"].close()
    await ctx["bot"].session.close()
    await ctx["engine"].dispose()


class WorkerSettings:
    functions = [
        notify_users,
        notify_user,
        send_cart_confirmation_msg,
        notify_expired_payment,
        notify_expiring_payment,
        free_stock_in_cancelled_orders,
        auto_close_completed_orders,
        auto_enable_bot,
    ]
    on_startup = startup
    on_shutdown = shutdown
    on_job_start = on_job_start
    after_job_end = after_job_end
    timezone = pytz.timezone("Europe/Moscow")
    allow_abort_jobs = True
    redis_settings = config.redis.pool_settings
    cron_jobs = [
        cron(
            free_stock_in_cancelled_orders,
            microsecond=0,
            max_tries=2,
            run_at_startup=True,
        ),
        cron(
            auto_close_completed_orders,
            microsecond=0,
            max_tries=2,
            run_at_startup=True,
        ),
    ]
